package org.vesselonline.mail;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;

public abstract class BriefingDisplay extends JPanel implements ActionListener {
  /**
   * For Serializable interface, value generated by Eclipse.
   */
  private static final long serialVersionUID = -2672361712680334025L;

  private final int tabIndex;

  private final JLabel timeLabel, messageLabel;
  private final JTable table;
  private final DefaultTableModel tableModel;
  private final javax.swing.Timer timer;

  protected BriefingDisplay(int tabIndex, String titleStr, int delay, Vector<String> columnNames) {
    super();
    this.tabIndex = tabIndex;

    // Create and set up the panel, add widgets
    this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

    // Create the widgets
    JPanel paneTtl = new JPanel(new BorderLayout());
    JLabel briefingLbl = new JLabel(titleStr);
    briefingLbl.setFont(DailyBriefingUtils.INSTANCE.getSmallFont());
    timeLabel = new JLabel("-not yet checked-", JLabel.RIGHT);
    timeLabel.setFont(DailyBriefingUtils.INSTANCE.getSmallFont());
    paneTtl.add(briefingLbl, BorderLayout.WEST);
    paneTtl.add(timeLabel, BorderLayout.EAST);
  
    // Build table to contain message headers, use TableModel so contents can be manipulated
    // Assumes first column is always "#" and should have a small fixed width
    tableModel = new DefaultTableModel(null, columnNames) {
      private static final long serialVersionUID = 3197657687606242411L;
      @Override
      public boolean isCellEditable(int row, int column) {
        // No cells in this table model are editable
        return false;
      }
    };

    table = createTable();
    TableColumn col = table.getColumnModel().getColumn(0);
    col.setMaxWidth(24);
    col.setResizable(false);

    // Make table scrollable
    JScrollPane paneScr = new JScrollPane(table);
    table.setPreferredScrollableViewportSize(new Dimension(360, 80));

    JPanel paneSts = new JPanel(new BorderLayout());
    messageLabel = new JLabel("-not yet checked-");
    messageLabel.setFont(DailyBriefingUtils.INSTANCE.getSmallFont());

    JButton actionBtn = new JButton("Refresh");
    actionBtn.setFont(DailyBriefingUtils.INSTANCE.getSmallFont());
    // Listen to events from the Refresh button
    actionBtn.addActionListener(this);

    paneSts.add(messageLabel, BorderLayout.WEST);
    paneSts.add(actionBtn, BorderLayout.EAST);

    // Add the widgets to the container
    this.add(paneTtl);
    this.add(paneScr);
    this.add(paneSts);

    // Check mail by starting the timer with a small initial delay
    // Have to reset the initial delay due to use of the restart
    timer = new javax.swing.Timer(DailyBriefingUtils.INSTANCE.getOneMinute() * delay, this);
//    timer.setInitialDelay(this.tabIndex * DailyBriefingUtils.INSTANCE.getOneMinute() / 3);
    timer.start();
//    timer.setInitialDelay(timer.getDelay());
  }

  public JLabel getMessageLabel() { return messageLabel; }
  public JLabel getTimeLabel() { return timeLabel; }
  public DefaultTableModel getTableModel() { return tableModel; }
  public JTable getTable() { return table; }

  public void actionPerformed(ActionEvent e) {
  	messageLabel.setText("Checking for updates . . .");

    final SwingWorker worker = new SwingWorker() {
      public Object construct() {
        try {
          BriefingDisplay.this.refresh();
          timer.restart();
        } catch (DailyBriefingException dbe) {
          handleException(dbe);
        } finally {
          // Trigger visual notification of updates (unset selection first to make sure that
          // actual tab selection causes ChangeEvent)
          ((JTabbedPane) BriefingDisplay.this.getParent()).setSelectedIndex(-1);
          ((JTabbedPane) BriefingDisplay.this.getParent()).setSelectedIndex(BriefingDisplay.this.tabIndex);
        }

        return null;
      }
    };
    worker.start();
  }

  protected abstract JTable createTable();
  protected abstract void refresh() throws DailyBriefingException;
  protected abstract void handleException(DailyBriefingException dbe);
}
